using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using XVUEfxSDK.Remoting;
using XVUEfxSDK.Xsequencer;

namespace ApplicationStandaloneRemoting
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            buttonDisconnect.Enabled = false;
            groupBoxProperties.Enabled = true;
            buttonConnect.Enabled = true;
            groupBoxUI.Enabled = false;
            buttonClearAll.Enabled = false;
            buttonPrepare.Enabled = false;
            groupBoxInitializeRuntimeTree.Enabled = false;
            groupBoxCaptureProperties.Enabled = false;
            buttonStartCapture.Enabled = false;
            buttonStopCapture.Enabled = false;
        }

        XvueFxSequencerClient client = new XvueFxSequencerClient();

        private void buttonConnect_Click(object sender, EventArgs e)
        {
            try
            {
                //connect to the remoting iOrasis at specified properties
                if (client.ActivateClient
                    (false,
                    textBoxRemotingIP.Text,
                    textBoxRemotePort.Text,
                    textBoxRemoteName.Text,
                    "9201"))
                {
                    buttonConnect.Enabled = false;
                    buttonDisconnect.Enabled = true;
                    groupBoxProperties.Enabled = false;
                    groupBoxUI.Enabled = true;
                    buttonClearAll.Enabled = true;
                    groupBoxInitializeRuntimeTree.Enabled = true;
                    groupBoxRuntimeEffects.Enabled = false;
                    buttonAddToRuntime.Enabled = false;
                    ClearCaptureProperties();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }

        private void buttonDisconnect_Click(object sender, EventArgs e)
        {
            try
            {
                //if capturint first close capture
                if(buttonStopCapture.Enabled)
                    buttonStopCapture_Click(this, null);
                groupBoxCaptureProperties.Enabled = false;
                buttonStartCapture.Enabled = false;
                buttonStopCapture.Enabled = false;
                if (client.CloseClient())
                {
                    buttonConnect.Enabled = true;
                    buttonDisconnect.Enabled = false;
                    groupBoxProperties.Enabled = true;
                    groupBoxUI.Enabled = false;
                    comboBoxSelectedEffect.Items.Clear();
                    comboBoxSelectedEffect.SelectedIndex = -1;
                    buttonPrepare.Enabled = false;
                    buttonAddToRuntime.Enabled = false;
                    buttonClearAll.Enabled = false;
                    groupBoxInitializeRuntimeTree.Enabled = false;
                    if(checkBoxClearAllOnDisconnect.Checked)
                        client.xSequencer.xCommand("XVUE", XvueSequencerCommandType.ClearAllItems);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (buttonDisconnect.Enabled)
                buttonDisconnect_Click(this, null);
        }

        private void buttonClearAll_Click(object sender, EventArgs e)
        {
            //clear all effects and nodes under the XVUE main effect node
            try
            {
                client.xSequencer.xCommand("XVUE", XvueSequencerCommandType.ClearAllItems);
                buttonPrepare.Enabled = true;
                comboBoxSelectedEffect.Items.Clear();
                comboBoxSelectedEffect.SelectedIndex = -1;
                checkBoxApplyDVEToLive.Checked = false;
                checkBoxApplyDVEToPlaylist.Checked = false;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                buttonDisconnect_Click(this, null);
            }
        }

        //here we create a basic effect structure
        //effects can be added dynamically or at the start of the application for static layouts
        private void buttonPrepare_Click(object sender, EventArgs e)
        {
            try
            {
                buttonPrepare.Enabled = false;
                groupBoxRuntimeEffects.Enabled = true;
                buttonAddToRuntime.Enabled = true;

                //add a swap layer to hold background item
                XvueSequencerSwapBase swapback = new XvueSequencerSwapBase();
                swapback.XvEffectTAG = "LayerBackground";
                client.xSequencer.xQueSequencerItem(swapback);

                //add a playlist. This effect will play sequencially any item or effect that will be added
                //on it
                XvueSequencerAutoPlaylistBase playlistA = new XvueSequencerAutoPlaylistBase();
                playlistA.XvEffectTAG = "PlaylistA";
                client.xSequencer.xQueSequencerItem(playlistA);

                //add a crawl.This effect will play sequencially (positioning them accordingly)
                //any item added to it
                XvueSequencerPositionalBase crawlA = new XvueSequencerPositionalBase();
                crawlA.XvEffectTAG = "CrawlA";
                crawlA.xVisualProperties.xPosition.Y = 200;
                client.xSequencer.xQueSequencerItem(crawlA);


                //add a second crawl Right to Left
                XvueSequencerPositionalBase crawlB = new XvueSequencerPositionalBase();
                crawlB.XvEffectTAG = "CrawlB";
                crawlB.xType = XvuePositionalEffectType.xLeftToRightCrawl;
                //crop the left part of the crawl
                //Cropping is the recommended way to position a crawl in the horizontal axis
                //xPosition.X would create crawl item positioning artifacts and thus should be avoided
                //Similarly you should use xPosition.X to position a Roll effect in the horizontal axis
                //and xCrop.top,bottom to position the Roll to the vertical axis
                crawlB.xVisualProperties.xCrop.xLeft = 200;
                //position in lower from crawlA
                crawlB.xVisualProperties.xPosition.Y = 400;

                client.xSequencer.xQueSequencerItem(crawlB);

                //add a swap effect. The swap effect is usefull to exchange one item with a new one
                XvueSequencerSwapBase swapA = new XvueSequencerSwapBase();
                swapA.XvEffectTAG = "SwapA";
                swapA.xVisualProperties.xPosition.X = 100;
                swapA.xVisualProperties.xPosition.Y = 100;
                swapA.xEffectIn = XvueSwapType.Fade;
                swapA.xDurationIn = 15;
                swapA.xEffectOut = XvueSwapType.Fade;
                swapA.xDurationOut = 15;
                client.xSequencer.xQueSequencerItem(swapA);

                comboBoxSelectedEffect.Items.Clear();
                comboBoxSelectedEffect.Items.Add("LayerBackground");
                comboBoxSelectedEffect.Items.Add("PlaylistA");
                comboBoxSelectedEffect.Items.Add("CrawlA");
                comboBoxSelectedEffect.Items.Add("CrawlB");
                comboBoxSelectedEffect.Items.Add("SwapA");
                comboBoxSelectedEffect.SelectedIndex = 0;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                buttonDisconnect_Click(this, null);
            }
        }


        private void buttonAddLive_Click(object sender, EventArgs e)
        {
            XvueSequencerItemLiveBase live = new XvueSequencerItemLiveBase();
            listBox1.Items.Add(live);
        }

        private void buttonAddVAFile_Click(object sender, EventArgs e)
        {
            try
            {
                OpenFileDialog openFileDialog1 = new OpenFileDialog();
                openFileDialog1.Filter = "All Video files(*.avi;*.wmv;*.mpg;*.mxf;*.mov;*.M2V)|*.avi;*.wmv;*.mpg;*.mxf;*.mov;*.m2v";
                if (openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    string xVideoFilename = openFileDialog1.FileName;
                    string xAudioFilename = "";
                    string xVideoMatteFilename = "";
                    //openFileDialog1.Filter = "All Video Matte files(*.avi;*.wmv;*.mpg)|*.avi;*.wmv;*.mpg";
                    //if (openFileDialog1.ShowDialog() == DialogResult.OK)
                    //{
                    //    xVideoMatteFilename = openFileDialog1.FileName;
                    //}
                    openFileDialog1.Filter = "All Audio files(*.wav;*.wma;*.mp3)|*.wav;*.wma;*.mp3";
                    if (openFileDialog1.ShowDialog() == DialogResult.OK)
                    {
                        xAudioFilename = openFileDialog1.FileName;
                    }
                    XvueSequencerItemAVFileBase av = client.xSequencer.xGetAVInfo(xVideoFilename, xVideoMatteFilename, xAudioFilename);
                    if ((av.xVideoType != XVUEfxSDK.xvueAVFileTypes.INVALID))
                    //&& (av.xVideoMatteType != XVUEfxSDK.xvueAVFileTypes.INVALID))
                    {
                        av.xTrimIn = 0;
                        //verify that Trimout is less than BOTH video and audio duration
                        av.xTrimOut = av.xVideoDuration;
                        if (av.xAudioDuration > 0)
                            if (av.xTrimOut > av.xAudioDuration)
                                av.xTrimOut = av.xAudioDuration;
                        listBox1.Items.Add(av);
                    }
                    else
                        MessageBox.Show("The av file reports as invalid or incompatible with current hardware");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                buttonDisconnect_Click(this, null);
            }

        }

        private void buttonAddText_Click(object sender, EventArgs e)
        {
            XvueSequencerItemTextBase text = new XvueSequencerItemTextBase();
            text.xText = textBox1.Text;
            text.xFontFamily = "Arial";
            text.xSize = 35;
            text.xPalette.ColorForeground = Color.FromArgb(255, 250, 250, 200);
            listBox1.Items.Add(text);

        }


        private void buttonAddImage_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();
            openFileDialog1.Filter = "All Image files(*.bmp;*.tif;*.jpg;*.psd;*.tga;*.png)|*.bmp;*.tif;*.jpg;*.psd;*.tga;*.png";
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                XvueSequencerItemImageBase im = new XvueSequencerItemImageBase();
                im.xPath = openFileDialog1.FileName;
                listBox1.Items.Add(im);
            }
        }

        private void buttonAddAnimation_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();
            openFileDialog1.Filter = "All Image files(*.bmp;*.tif;*.jpg;*.gif;*.tga;*.png)|*.bmp;*.tif;*.jpg;*.gif;*.tga;*.png";
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                XvueSequencerAnimationBase anim = new XvueSequencerAnimationBase();
                string fullpath = openFileDialog1.FileName;
                if (fullpath.Contains(".gif"))
                {
                    anim.XvPath = fullpath;
                }
                else
                {
                    string path = System.IO.Path.GetDirectoryName(fullpath);
                    string file = fullpath.Substring(path.Length + 1);
                    anim.XvPath = path + @"\" + file.Substring(0, 2) + "*" + fullpath.Substring(fullpath.Length - 4);
                }
                listBox1.Items.Add(anim);
            }

        }

        private void buttonAddWPF_Click(object sender, EventArgs e)
        {
            //if (openFileDialog1.ShowDialog() == DialogResult.OK)
            //{
            //    try
            //    {
            //        XmlReader xml = XmlReader.Create(openFileDialog1.FileName);
            //        Object obj = System.Windows.Markup.XamlReader.Load(xml);
            //        //                if (obj is .GetType() == typeof(System.Windows.Controls.Viewport3D))
            //        {
            //            SequencerWPF wpf = SequencerWPF.CreateItem(obj as System.Windows.UIElement, 720, 576);
            //            xAddItemToItem(wpf);
            //        }
            //        xml.Close();
            //    }
            //    catch (Exception ex)
            //    {
            //        MessageBox.Show(ex.Message);
            //    }
            //}
            //else
            //{
            //    //System.Windows.Media.FormattedText text = new System.Windows.Media.FormattedText("asdkfhaksdhf",
            //    //new System.Globalization.CultureInfo("en-us"),
            //    //System.Windows.FlowDirection.LeftToRight,
            //    //new System.Windows.Media.Typeface(new System.Windows.Media.FontFamily("Arial")/*this.FontFamily*/, System.Windows.FontStyles.Normal, System.Windows.FontWeights.Bold, new System.Windows.FontStretch()),
            //    //72,
            //    //new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Red));
            //    System.Windows.Controls.Button butt = new System.Windows.Controls.Button();
            //    butt.Content = "iOrasis sample WPF UI Element";
            //    System.Windows.Controls.StackPanel stackpanel = new System.Windows.Controls.StackPanel();
            //    stackpanel.Children.Add(butt);
            //    butt.FontSize = 30;
            //    System.Windows.Controls.TextBox butt2 = new System.Windows.Controls.TextBox();
            //    butt2.Text = "You see a stack panel with One button and one Textbox";
            //    stackpanel.Children.Add(butt2);
            //    butt2.FontSize = 24;
            //    butt2.Foreground = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Blue);
            //    //System.Windows.Controls.Canvas canv = new System.Windows.Controls.Canvas();
            //    //canv.Width = 100;
            //    //canv.Height = 100;
            //    //canvas.Children.Add(canv);
            //    //canv.Children.Add(text);
            //    //            System.Windows.Media.DrawingVisual drawingVisual = new System.Windows.Media.DrawingVisual();
            //    //System.Windows.Media.DrawingContext drawingContext = canv.RenderOpen
            //    //drawingContext.DrawRectangle(new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Black), null, new System.Windows.Rect(new System.Windows.Size(360, 180)));
            //    //drawingContext.DrawText(text, new System.Windows.Point(20, 50));
            //    //drawingContext.Close();
            //    SequencerWPF wpf = SequencerWPF.CreateItem(stackpanel, 720, 576);
            //    xAddItemToItem(wpf);
            //}

        }

        private void buttonAddTimecode_Click(object sender, EventArgs e)
        {
            SequencerTimecode timecode = new SequencerTimecode();
            timecode.DigitsFrameCountType = EnumSequencerTimecodeFrameDraw.mSeconds1000;
            timecode.DigitsFrames.TextProperties.Size = 40;
            listBox1.Items.Add(timecode);
        }

        private void checkBoxApplyDVEToLive_CheckedChanged(object sender, EventArgs e)
        {
            try
            {
                XvueSequencerItemRef itemref = client.xSequencer.xGetItemRef("LayerBackground");
                if (itemref != null)
                    if (checkBoxApplyDVEToLive.Checked)
                    {
                        //use 2DDVE to scale in half
                        //move it also a bit
                        itemref.xVisualProperties.xScale.X = 0.5;
                        itemref.xVisualProperties.xScale.Y = 0.5;
                        itemref.xVisualProperties.xPosition.X = 100;
                        itemref.xVisualProperties.xPosition.Y = 100;
                    }
                    else
                    {
                        itemref.xVisualProperties.xPosition.X = 0;
                        itemref.xVisualProperties.xPosition.Y = 0;
                        itemref.xVisualProperties.xScale.X = 1;
                        itemref.xVisualProperties.xScale.Y = 1;
                    }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                buttonDisconnect_Click(this, null);
            }
        }

        private void checkBoxApplyDVEToPlaylist_CheckedChanged(object sender, EventArgs e)
        {
            try
            {
                XvueSequencerItemRef itemref = client.xSequencer.xGetItemRef("PlaylistA");
                if (itemref != null)
                    if (checkBoxApplyDVEToPlaylist.Checked)
                    {
                        //use 2DDVE to scale in half the whole playlist with whatever plays in it
                        itemref.xVisualProperties.xScale.X = 0.5;
                        itemref.xVisualProperties.xScale.Y = 0.5;
                    }
                    else
                    {
                        itemref.xVisualProperties.xScale.X = 1;
                        itemref.xVisualProperties.xScale.Y = 1;
                    }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                buttonDisconnect_Click(this, null);
            }

        }

        private void buttonClearEffectChildren_Click(object sender, EventArgs e)
        {
            client.xSequencer.xCommand(comboBoxSelectedEffect.SelectedItem as string,
                XvueSequencerCommandType.ClearAllItems);
        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            propertyGrid1.SelectedObject = listBox1.SelectedItem;
        }

        private void buttonAddToRuntime_Click(object sender, EventArgs e)
        {
            if (listBox1.SelectedItem != null)
            {
                try
                {
                    XvueSequencerItemBase item = listBox1.SelectedItem as XvueSequencerItemBase;
                    item.XvParentEffectTAG = comboBoxSelectedEffect.SelectedItem as string;
                    client.xSequencer.xQueSequencerItem(item);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    buttonDisconnect_Click(this, null);
                }
            }
        }

        private void buttonClearTemporaryList_Click(object sender, EventArgs e)
        {
            listBox1.Items.Clear();
            propertyGrid1.SelectedObject = null;
        }


        //capture
        private void ClearCaptureProperties()
        {
            comboBoxCaptureFormats.Items.Clear();
            //enumerate all compressions. here I should change the codecs depending on SD or HD resolution
            //the proper way to do it would be by Getting resolution from IXvueSequencerUser.GetResolution
            //and then add only the appropriate codecs in the combobox
            foreach (XVUEfxSDK.EnumCaptureCodec codec in Enum.GetValues(typeof(XVUEfxSDK.EnumCaptureCodec)))
            {
                comboBoxCaptureFormats.Items.Add(codec);
            }
            comboBoxCaptureFormats.SelectedIndex = 0;
            textBoxCaptureAudioPath.Text = "";
            textBoxCaptureVideoPath.Text = "";
            checkBoxAudioInterleaved.Checked = false;
            groupBoxAudioCaptureProperties.Enabled = false;
            checkBoxCaptureAudio.Checked = false;
            checkBoxCaptureTDIR.Checked = false;
            buttonStartCapture.Enabled = true;
            buttonStopCapture.Enabled = false;
            groupBoxCaptureProperties.Enabled = true;
        }

        private void buttonStartCapture_Click(object sender, EventArgs e)
        {
            XvueCapture capturemain = new XvueCapture();
            XvueAVFileCaptureInfo capoutput = new XvueAVFileCaptureInfo();

            capoutput.CaptureCompression = (XVUEfxSDK.EnumCaptureCodec)(comboBoxCaptureFormats.SelectedItem);
            capoutput.VideoPath = textBoxCaptureVideoPath.Text;
            capoutput.TDIR = checkBoxCaptureTDIR.Checked;
            capoutput.TDIRInterval = 1.0f;
            //The user must create a proper user interface that will handle all the 
            //different combinations of capture formats and their respective audio types
            //eg. interleaved or not, allowed or not, SD or HD etc
            if (checkBoxCaptureAudio.Checked)
            {
                capoutput.CaptureAudio = checkBoxCaptureAudio.Checked;
                if (checkBoxAudioInterleaved.Checked)
                    capoutput.IsInterleaved = true;
                else
                    capoutput.AudioPath = textBoxCaptureAudioPath.Text;
                switch(comboBoxCaptureAudioChannels.SelectedIndex)
                {
                    case 0:
                        {capoutput.AudioChannels = 2;}break;
                    case 1:default:
                        { capoutput.AudioChannels = 4; } break;
                    case 2:
                        { capoutput.AudioChannels = 8; } break;
                }
                //must change this when capturing WMV
                capoutput.AudioBits = XVUEfxSDK.XvueCaptureAudioBits.Bit24;
            }

            //multiple output captures can be added to facilitate the possibility of capturing
            //in different formats simultaneously like proxy etc.
            capturemain.AddCaptureOutput(capoutput);

            //if multiple channels capture is needed then multiple commands to the corresponding
            //IXvueSequencerUser interfaces must be send
            if(client.xSequencer.xStartCapture(capturemain))
            {
                groupBoxCaptureProperties.Enabled = false;
                buttonStopCapture.Enabled = true;
                buttonStartCapture.Enabled = false;
            }
            else
                MessageBox.Show("Error starting capture. Please check iOrasis log, the capture information as also the number of audio channels");
        }

        private void buttonStopCapture_Click(object sender, EventArgs e)
        {
            if (!client.xSequencer.xStopCapture())
            {
                MessageBox.Show("Error stoping capture.Please check iOrasis log");
            }
            else
            {
                groupBoxCaptureProperties.Enabled = true;
                buttonStartCapture.Enabled = true;
                buttonStopCapture.Enabled = false;
            }
        }

        private void checkBoxAudioInterleaved_CheckedChanged(object sender, EventArgs e)
        {
            buttonCaptureAudioPath.Enabled = !checkBoxAudioInterleaved.Checked;
            textBoxCaptureAudioPath.Enabled = !checkBoxAudioInterleaved.Checked;
            textBoxCaptureAudioPath.Text = "";
        }

        private void buttonCaptureAudioPath_Click(object sender, EventArgs e)
        {
            SaveFileDialog filedialog = new SaveFileDialog();
            filedialog.Title = "Capture Audio file";
            filedialog.Filter = "WAV files|*.WAV";//add more if needed
            if (filedialog.ShowDialog(this) == DialogResult.OK)
            {
                textBoxCaptureAudioPath.Text = filedialog.FileName;
            }
        }

        private void buttonCaptureVideoPath_Click(object sender, EventArgs e)
        {
            SaveFileDialog filedialog = new SaveFileDialog();
            filedialog.Title = "Capture Video file";
            filedialog.Filter = "AVI files|*.AVI|MXF files|*.MXF|WMV files|*.WMV";//add more if needed
            if (filedialog.ShowDialog(this) == DialogResult.OK)
            {
                textBoxCaptureVideoPath.Text = filedialog.FileName;
            }
        }

        private void checkBoxCaptureAudio_CheckedChanged(object sender, EventArgs e)
        {
            groupBoxAudioCaptureProperties.Enabled = checkBoxCaptureAudio.Checked;
            textBoxCaptureAudioPath.Text = "";
            comboBoxCaptureAudioChannels.SelectedIndex = 1;
        }


    }
}